﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Numerics;

namespace ContinuedFraction
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        string NumberDivide(BigInteger dividend, BigInteger divisor, int decimals)
        {
            BigInteger quotient, remainder;

            quotient = BigInteger.DivRem(dividend * BigInteger.Parse("1" + new String('0', decimals)), divisor, out remainder);

            if (remainder > (divisor >> 1))
            {
                quotient++;
            }

            string value = quotient.ToString();

            if (decimals > 0)
            {
                if (value.Length <= decimals)
                {
                    value = value.PadLeft(decimals + 1, '0');
                }

                value = value.Insert(value.Length - decimals, ".");
            }

            return value;
        }

        void ContinueFraction(BigInteger[] arrarNumber, int count, out BigInteger numerator, out BigInteger denominator)
        {
            numerator = 0;
            denominator = 1;

            if (count > arrarNumber.Length)
            {
                count = arrarNumber.Length;
            }

            for (int i = count - 1; i >= 0; i--)
            {
                BigInteger n;

                if (arrarNumber[i] >= 0)
                {
                    n = denominator * arrarNumber[i] + numerator;
                }
                else
                {
                    n = -(denominator * (-arrarNumber[i]) + numerator);
                }

                numerator = denominator;
                denominator = n;
            }

            {
                BigInteger n = numerator;
                numerator = denominator;
                denominator = n;
            }
        }

        string ContinueFractionShow(BigInteger[] arrarNumber, int count)
        {
            StringBuilder strTmp = new StringBuilder();

            if (count > arrarNumber.Length)
            {
                count = arrarNumber.Length;
            }

            strTmp.Append("[");
            for (int i = 0; i < count; i++)
            {
                if (i == 1)
                {
                    strTmp.Append(";");
                }
                else if (i > 1)
                {
                    strTmp.Append(",");
                }
                strTmp.Append(arrarNumber[i].ToString());
            }
            strTmp.Append("]");

            return strTmp.ToString();
        }

        private void buttonCalc_Click(object sender, EventArgs e)
        {
            try
            {
                int decimals = (int)numericUpDownRound.Value;
                List<BigInteger> listNum = new List<BigInteger>();
                string strNum = textBoxNum.Text.Trim().Replace(" ", "");

                if ((strNum[0] == '[') && (strNum[strNum.Length - 1] == ']'))
                {
                    strNum = strNum.Remove(strNum.Length - 1, 1);
                    strNum = strNum.Remove(0, 1);

                    string[] strs = strNum.Split(';');

                    listNum.Add(BigInteger.Parse(strs[0]));

                    strs = strs[1].Split(',');
                    for (int i = 0; i < strs.Length; i++)
                    {
                        BigInteger num = BigInteger.Parse(strs[i]);
                        if (num <= 0)
                        {
                            throw new Exception("连分数分母项必须大于0。");
                        }
                        listNum.Add(num);
                    }
                }
                else
                {
                    BigInteger dividend, divisor;

                    // 输入解析
                    int posPoint = strNum.IndexOf(".");
                    if (posPoint >= 0)
                    {
                        if (posPoint == 0)
                        {
                            strNum = "0" + strNum;
                            posPoint++;
                        }

                        if (posPoint == strNum.Length - 1)
                        {
                            strNum = strNum + "0";
                        }

                        BigInteger.Parse(strNum.Substring(0, posPoint));
                        BigInteger.Parse(strNum.Substring(posPoint + 1));
                        dividend = BigInteger.Parse(strNum.Remove(posPoint, 1));
                        divisor = BigInteger.Parse("1" + new String('0', strNum.Substring(posPoint + 1).Length));
                    }
                    else
                    {
                        dividend = BigInteger.Parse(strNum);
                        divisor = 1;
                    }

                    // 计算连分数
                    while (divisor > 0)
                    {
                        BigInteger quotient, remainder;

                        quotient = BigInteger.DivRem(dividend, divisor, out remainder);
                        listNum.Add(quotient);
                        if (quotient < 0)
                        {
                            quotient = BigInteger.DivRem(-dividend, divisor, out remainder);
                        }

                        dividend = divisor;
                        divisor = remainder;
                    }
                }

                // 显示结果
                {
                    StringBuilder strTmp = new StringBuilder();
                    BigInteger numerator, denominator;
                    BigInteger[] arrarNumber = listNum.ToArray();

                    slab_round.Text = "精度:" + decimals.ToString();
                    slab_count.Text = "项数:" + arrarNumber.Length.ToString();

                    strTmp.Append("str=>\t" + textBoxNum.Text + "\r\n");
                    ContinueFraction(arrarNumber, arrarNumber.Length, out numerator, out denominator);
                    strTmp.Append("num=>\t" + NumberDivide(numerator, denominator, decimals) + "\r\n");
                    strTmp.Append("ctf=>\t" + ContinueFractionShow(arrarNumber, arrarNumber.Length) + "\r\n");
                    strTmp.Append("\r\n");

                    for (int i = 0; i < arrarNumber.Length; i++)
                    {
                        ContinueFraction(arrarNumber, i + 1, out numerator, out denominator);
                        strTmp.Append((i + 1).ToString() + "=>\t" + NumberDivide(numerator, denominator, decimals) + "\t");
                        strTmp.Append(arrarNumber[i].ToString() + "\t");
                        strTmp.Append(numerator.ToString() + "/" + denominator.ToString() + "\r\n");
                    }

                    textBoxResult.Text = strTmp.ToString();
                }
            }
            catch (Exception err)
            {
                textBoxResult.Text = "error:" + err.Message;
            }
        }

        private void textBoxNum_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == System.Convert.ToChar(13))
            {
                buttonCalc_Click(null, null);
                e.Handled = true;
            }
        }

        private void slab_info_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.mysoow.com");  // 在浏览器中打开链接
        }
    }
}
